package com.shaozi.nc.quartz.crm;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ReflectionUtils;
import com.shaozi.lib.throwable.SzException;
import com.shaozi.nc.data.hibVO.CrmCustomerVO;
import com.shaozi.nc.data.hibVO.CrmToOpenseaCustomerVO;
import com.shaozi.nc.data.model.SecretaryModel;
import com.shaozi.nc.hibservice.CrmCustomerService;
import com.shaozi.nc.hibservice.CrmOpenSeeRuleService;
import com.shaozi.nc.hibservice.CrmPipelineService;
import com.shaozi.nc.hibservice.CrmPipelineStageService;
import com.shaozi.nc.hibservice.CrmToOpenseaCustomerService;
import com.shaozi.nc.manage.secretary.SecretaryManage;
import com.shaozi.nc.quartz.base.BaseRuleJobExecute;
import com.shaozi.nc.quartz.crm.pojo.OpenSeeRulePipelinePojo;
import com.shaozi.nc.quartz.crm.pojo.UserCountPojo;
import com.shaozi.utils.common.BeanUtils;
import com.shaozi.utils.spel.SimpleEval;

public abstract class CrmOpenSeeBaseExecute extends BaseRuleJobExecute {
	// 设置类型
	protected static int type = 1;

	private Logger logger = Logger.getLogger(CrmOpenSeeBaseExecute.class);
	public static final int Type_Recover = 0;
	public static final int Type_Quite = 1;
	private String toOpenseaCustomerTitle;
	/**
	 * 1跟进,
	 */
	public static final int BackType_Activity = 1;
	/**
	 * 2成单
	 */
	public static final int BackType_Order = 2;

	public static final int[] BackTypes = new int[] { BackType_Activity, BackType_Order };

	/**
	 * 不区别：跟进或成单
	 */
	protected Map<String, UserCountPojo> uniquePipelineIds = new HashMap<>();

	protected Map<Integer, String> noBackMethods = new HashMap<>();

	private Map<Integer, String> noBackDaysProps = new HashMap<>();
	/**
	 * noActivityBackGroupByUser,noOrderBackGroupByUser
	 */
	protected Map<Integer, String> noBackGroupByUserMethods = new HashMap<>();

	@Autowired
	protected CrmCustomerService crmCustomerService;
	@Autowired
	protected BeanUtils beanUtils;
	@Autowired
	protected CrmToOpenseaCustomerService crmToOpenseaCustomerService;
	@Autowired
	protected CrmPipelineService crmPipelineService;
	@Autowired
	protected CrmPipelineStageService crmPipelineStageService;
	@Autowired
	protected SecretaryManage secretaryMgr;
	@Autowired
	protected CrmOpenSeeRuleService crmOpenSeeRuleService;

	public CrmOpenSeeBaseExecute() {
		super();
		toOpenseaCustomerTitle = beanUtils.getConfig().getValue("log.crm.toopensea.customer");

		noBackDaysProps.put(BackType_Activity, "noActivityDay");
		noBackDaysProps.put(BackType_Order, "noOrderDay");

	}

	@SuppressWarnings("unchecked")
	protected void saveToOpenseaCustomer(String companyId, int backType, List<OpenSeeRulePipelinePojo> ruleVos,
			List<Integer> stageIds, int type, List<UserCountPojo> userTotalCounts, long key, boolean amalgamate) {
		final String methodName = noBackMethods.get(backType);
		Method serviceMethod = ReflectionUtils.findMethod(CrmCustomerService.class, methodName, String.class,
				OpenSeeRulePipelinePojo.class, List.class, List.class);
		final SimpleEval eval = new SimpleEval();

		ruleVos.forEach(ruleVo -> {
			try {
				List<CrmCustomerVO> customerVos = null;
				// 合并记录 变成一条记录
				if (amalgamate) {
					List<Integer> exceptCustomerIds = getExceptCustomerIds(userTotalCounts, ruleVo.getPipelineId());
					customerVos = (List<CrmCustomerVO>) serviceMethod.invoke(crmCustomerService, companyId, ruleVo,
							stageIds, exceptCustomerIds);
				} else {// 变成两条记录
					customerVos = (List<CrmCustomerVO>) serviceMethod.invoke(crmCustomerService, companyId, ruleVo,
							stageIds, null);
				}

				if (customerVos != null) {
					Map<String, Object> params = new HashMap<>();
					params.put("days",
							org.apache.commons.beanutils.BeanUtils.getProperty(ruleVo, noBackDaysProps.get(backType)));
					params.put("backTypeTitle", getBackTypeTitle(backType));
					final String c = (String) eval.eval(toOpenseaCustomerTitle, params);
					customerVos.forEach(customer -> {
						CrmToOpenseaCustomerVO vo = new CrmToOpenseaCustomerVO();
						Integer customerId = customer.getId();
						vo.setCustomerId(customerId);
						vo.setName(customer.getName());
						vo.setOwnerUid(customer.getOwnerUid());
						vo.setReason(c);
						vo.setType(type);
						vo.setPipelineId(customer.getPipelineId());
						vo.setExecuteTime(getKey(key, backType));
						try {
							crmToOpenseaCustomerService.save(vo);
						} catch (Exception e) {
							logger.error(SzException.getStackMessage(e));
						}
					});
				}
			} catch (Exception e) {
				logger.error(SzException.getStackMessage(e));
			}
		});
	}

	protected void sendSecretary(String companyId, List<SecretaryModel> secretarys) throws SzException {
		secretaryMgr.handleByPushType(companyId, secretarys);
	}

	protected String getBackTypeTitle(int backType) {
		switch (backType) {
		case BackType_Activity:
			return "跟进";
		default:
			return "成单";
		}
	}

	protected String getCustomTypeTitle(int type) {
		switch (type) {
		case 1:
			return "客服";
		default:
			return "销售";
		}
	}

	// protected String getKey(long key, int backType) {
	// return backType + "_" + key;
	// }

	protected String getKey(long key, int backType) {
		return type + "_" + key;
	}

	protected String getUniqueKey(int pipelineId, int userId) {
		return String.format("%d_%d", pipelineId, userId);
	}

	private List<Integer> getExceptCustomerIds(List<UserCountPojo> userTotalCounts, int pipelineId) {
		List<UserCountPojo> pojos = getUserCountPojos(userTotalCounts, pipelineId);
		if (pojos == null || pojos.isEmpty())
			return null;
		List<Integer> ret = new ArrayList<>();
		pojos.forEach(pojo -> ret.addAll(pojo.getCustomerIds().keySet()));
		return ret;
	}

	/**
	 * 预提醒中如果不考虑只有两个backtype的情况下，可能有多条UserCountPojo
	 * 
	 * @param userTotalCounts
	 * @param pipelineId
	 * @return
	 */
	private List<UserCountPojo> getUserCountPojos(List<UserCountPojo> userTotalCounts, int pipelineId) {
		List<UserCountPojo> ret = new ArrayList<>();
		for (UserCountPojo pojo : userTotalCounts) {
			if (pipelineId == pojo.getPipelineId()) {
				ret.add(pojo);
			}
		}
		return ret;
	}

	@Override
	protected void handleCompany(String companyId) throws SzException {
		uniquePipelineIds.clear();
		long key = System.currentTimeMillis();
		final List<UserCountPojo> userTotalCounts = new ArrayList<>();
		for (int backType : BackTypes) {
			try {
				scheduleGroupByUser(companyId, backType, userTotalCounts, key);
			} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
				logger.error(SzException.getStackMessage(e));
			}
		}
		userTotalCounts.forEach(pojo -> {
			try {
				pojo.setCount((long) pojo.getCustomerIds().size());
				List<SecretaryModel> secretarys = getSecretaryModes(companyId, type, pojo.getUserId(),
						pojo.getPipelineId(), pojo.getCount(), key);
				sendSecretary(companyId, secretarys);
			} catch (Exception e) {
				logger.error(SzException.getStackMessage(e));
			}
		});
	}

	/**
	 * 通用抽象组装发送实例
	 * 
	 * @param companyId
	 * @param backType
	 * @param userId
	 * @param pipelineId
	 * @param counts
	 * @param key
	 * @return
	 * @throws SzException
	 */
	protected abstract List<SecretaryModel> getSecretaryModes(String companyId, int backType, int userId,
			int pipelineId, long counts, long key) throws SzException;

	protected abstract void scheduleGroupByUser(String companyId, int backType,
			final List<UserCountPojo> userTotalCounts, long key)
			throws SzException, IllegalAccessException, IllegalArgumentException, InvocationTargetException;
}
